package com.cyh.greendaoupgrade.greendao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.cyh.greendaoupgrade.greendao.dao.BookItem2Dao;
import com.cyh.greendaoupgrade.greendao.dao.DaoMaster;
import com.cyh.greendaoupgrade.greendao.dao.StudentItemDao;
import com.cyh.greendaoupgrade.greendao.dao.TeacherItemDao;
import com.cyh.greendaoupgrade.greendao.dao.UserItemDao;


import org.greenrobot.greendao.AbstractDao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;


/**
 * Created by WB on 2017/7/7.
 * 用于数据的升级
 */

/**
 * 可以继承自OpenHelper或者DevOpenHelper
 * OpenHelper:创建表，默认升级表是不做任何操作 ---必须选这个
 * DevOpenHelper:创建表，默认升级表示删除所有表，然后新建空的表 --不能选这个，会删除所有表
 * 我们重新实现升级逻辑
 * 增加数据库版本号
 * gradle一下
 * 添加application，并DBUtils.getInstance(this).getDaoSession();
 * GreenDaoHelper.java中属性和initDao函数需要改动
 * 支持添加字段
 * 支持删除字段
 * 支持添加表，也需要增加版本号, 需要将表的dao加入upgradeTable，否则会报错,
 * 支持删除表 -- 少用
 * 支持修改字段名字 -- 少用，等价于删除字段，再添加另外一个字段
 * 不支持修改字段类型
 *
 *
 * 编译出现奇怪的问题，可以删除dao文件夹里面的文件，model文件夹里面的文件自动生成部分删除
 * MigrationHelper.java和DBMigrationHelper.java都可以用
 * DBMigrationHelper.java 添加表会报错
 * */
public class SQLiteOpenHelper extends DaoMaster.OpenHelper {
    private final static String TAG = "SQLiteOpenHelper";
    private static HashMap<Integer, List<Class<? extends AbstractDao<?, ?>>>> upgradeTable = new HashMap<>();
    private static HashMap<Integer, List<String>> deleteTable = new HashMap<>();
    static {
        //添加每一个版本涉及到修改的表
        /*************************更新表*********************/
        upgradeTable.put(2, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(UserItemDao.class);
            add(StudentItemDao.class);
        }});
        upgradeTable.put(3, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(UserItemDao.class);
            add(StudentItemDao.class);
        }});
        upgradeTable.put(4, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(TeacherItemDao.class);
        }});
        upgradeTable.put(6, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(TeacherItemDao.class);
        }});
        upgradeTable.put(7, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(TeacherItemDao.class);
        }});
        upgradeTable.put(8, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(TeacherItemDao.class);
        }});
        upgradeTable.put(9, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(TeacherItemDao.class);
        }});
        upgradeTable.put(11, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(UserItemDao.class);
        }});
        upgradeTable.put(12, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(UserItemDao.class);
        }});
        upgradeTable.put(13, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(StudentItemDao.class);
        }});
        upgradeTable.put(14, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(StudentItemDao.class);
        }});
        upgradeTable.put(15, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(StudentItemDao.class);
        }});

        upgradeTable.put(20, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(BookItem2Dao.class);
        }});
        upgradeTable.put(21, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(BookItem2Dao.class);
        }});
        upgradeTable.put(23, new ArrayList<Class<? extends AbstractDao<?, ?>>>(){{
            add(BookItem2Dao.class);
        }});



        /************************删除表**********************/
        deleteTable.put(10, new ArrayList<String>(){{
            add("TEACHER_ITEM");
        }});
    }
    public SQLiteOpenHelper(Context context, String name) {
        super(context, name);
    }

    /**
     *
     *
     * */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);
        Log.i(TAG, "数据库升级：oldVersion = " + oldVersion + "---newVersion = " + newVersion);
        if(oldVersion < newVersion) {
            Log.i(TAG, "数据库升级：oldVersion < newVersion");
            upgradeTable(db, oldVersion, newVersion);
            deleteTable(db, oldVersion, newVersion);
        }



        //下面这些代码不需要，只用于参考
        //设置需要升级的表
        /*MigrationHelper.migrate(db,
                UserItemDao.class);*/

       /* MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
            @Override
            public void onCreateAllTables(Database db, boolean ifNotExists) {
                DaoMaster.createAllTables(db, ifNotExists);
            }
            @Override
            public void onDropAllTables(Database db, boolean ifExists) {
                DaoMaster.dropAllTables(db, ifExists);
            }
        },GroupDao.class, TestData2Dao.class, TestData3Dao.class);*/
    }

    private void upgradeTable(SQLiteDatabase db, int oldVersion, int newVersion) {
        List<Class<? extends AbstractDao<?, ?>>> listClass = new ArrayList<>();
        Set<Integer> keys = upgradeTable.keySet();
        Log.i(TAG, "数据库升级：keys = " + keys.size());
        Iterator<Integer> iterable = keys.iterator();
        while (iterable.hasNext()) {
            Integer it = iterable.next();
            if(oldVersion < it.intValue() && newVersion >= it.intValue()) {
                List<Class<? extends AbstractDao<?, ?>>> items = upgradeTable.get(it);
                for(Class<? extends AbstractDao<?, ?>> item : items) {
                    if(!listClass.contains(item)) {
                        listClass.add(item);
                    }
                }
            }
        }
        if(listClass.size() > 0) {
            Log.i(TAG, "数据库升级：listClass = " + listClass);
            Log.i(TAG, "数据库升级：listClass.size() = " + listClass.size());
            //第一种方法
            MigrationHelper.migrate(db, listClass);

            //第二种方法
            /*DBMigrationHelper migratorHelper = new DBMigrationHelper();
            migratorHelper.onUpgrade(db, listClass);*/

        }
    }

    private void deleteTable(SQLiteDatabase db, int oldVersion, int newVersion) {
        List<String> listClass = new ArrayList<>();
        Set<Integer> keys = deleteTable.keySet();
        Log.i(TAG, "数据库表删除：keys = " + keys.size());
        Iterator<Integer> iterable = keys.iterator();
        while (iterable.hasNext()) {
            Integer it = iterable.next();
            if(oldVersion < it.intValue() && newVersion >= it.intValue()) {
                List<String> items = deleteTable.get(it);
                for(String item : items) {
                    if(!listClass.contains(item)) {
                        Log.i(TAG, "数据库表删除：table = " + item);
                        db.execSQL("drop table " + item);
                    }
                }
            }
        }
    }
}
